﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Xml.Linq;

namespace Common
{
    public sealed class DynamicJsonObject : DynamicJson
    {
        public DynamicJsonObject(JsonNode element, JsonSerializerOptions options) : base(element, options)
        {
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            var valueKind = GetMember(binder.Name, out result);
            return true;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            if (Element.AsObject().ContainsKey(binder.Name))
            {
                Element[binder.Name].ReplaceWith(value);
            }
            else
            {
                return Element.AsObject().TryAdd(binder.Name, JsonSerializer.SerializeToNode(value, JsonHelper.JsonSerializerOptions));
            }
            return true;
        }

        JsonValueKind GetMember(string name, out object result)
        {
            result = null;
            if (Element.AsObject().ContainsKey(name))
            {
                JsonNode elNode = Element[name];
                if (elNode != null)
                {
                    var valueKind = elNode.GetValueKind();
                    switch (valueKind)
                    {
                        case JsonValueKind.Undefined:
                        case JsonValueKind.Null:
                            break;
                        case JsonValueKind.Array:
                            result = elNode.GetValue<DynamicJsonArray>();
                            break;
                        case JsonValueKind.True:
                        case JsonValueKind.False:
                        case JsonValueKind.Number:
                        case JsonValueKind.String:
                            result = new DynamicJsonValue(elNode.AsValue(), JsonHelper.JsonSerializerOptions);
                            break;
                        case JsonValueKind.Object:
                            result = new DynamicJsonObject(elNode.AsObject(), JsonHelper.JsonSerializerOptions);
                            break;
                    }
                    return valueKind;
                }
            }
            return JsonValueKind.Null;
        }

        #region implicit
        public static implicit operator string(DynamicJsonObject json)
        {
            //return json.element.GetValueKind() == JsonValueKind.String
            //    ? json.element.GetValue<string>()
            //    : json.Element.GetRawText();
            return json.Element.ToJsonString();
        }
        #endregion
    }
}
